package com.teamwings.ctrls.service.impl;

import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.util.JdbcConstants;
import com.google.common.collect.Lists;
import com.teamwings.common.constant.FormConstant;
import com.teamwings.common.exception.ResultException;
import com.teamwings.ctrls.entity.DatabaseTableWithColumns;
import com.teamwings.ctrls.service.ILogicTableService;
import com.teamwings.modules.design.service.IDesignService;
import com.teamwings.modules.design.vo.FormTableVo;
import com.teamwings.modules.head.entity.FormTableHead;
import com.teamwings.modules.head.service.IFormTableHeadService;
import com.teamwings.modules.page.service.IPageService;
import com.teamwings.util.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.parser.SimpleNode;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.*;
import net.sf.jsqlparser.util.deparser.ExpressionDeParser;
import net.sf.jsqlparser.util.deparser.SelectDeParser;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.util.CommonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ILogicTableServiceImpl implements ILogicTableService {

    @Autowired
    private IFormTableHeadService formTableHeadService;
    @Autowired
    private IDesignService designService;
    @Autowired
    private IPageService pageService;

    /**
     * 只获取form_table_head相关的数据
     * [
     * {
     * "id" => ?,
     * "tableCname" => ?
     * }
     * ]
     *
     * @return
     */
    @Override
    public List<Map<String, String>> tableCnameList() {
        List<FormTableHead> latestList = formTableHeadService.getLatestList();
        ArrayList<Map<String, String>> mapList = Lists.newArrayList();
        for (FormTableHead formTableHead : latestList) {
            HashMap<String, String> map = new HashMap<>();
            map.put("id", formTableHead.getId());
            map.put("tableCname", formTableHead.getTableCname());
            mapList.add(map);
        }
        return mapList;
    }

    /**
     * 只获取form_table_head相关的数据
     *
     * @return
     */
    @Override
    public List<Map<String, String>> tableList() {
        List<FormTableVo> latestList = designService.getLatestList();

        ArrayList<Map<String, String>> mapList = Lists.newArrayList();
        for (FormTableVo formTableVo : latestList) {
            HashMap<String, String> map = new HashMap<>();
            map.put("tableHeadId", formTableVo.getTableHeadId());
            map.put("formId", formTableVo.getTableHeadId());
            map.put("tableCname", formTableVo.getTableCname());
            map.put("fields", formTableVo.getTableFields());
            mapList.add(map);
        }

        return mapList;
    }

    @Override
    public List<Map<String, String>> tableList(Boolean allTable) {
        if (!allTable) {
            // 只获取form_table_head关联的数据表
            return this.tableList();
        }

        // 获取所有的表
        List<FormTableVo> latestList = designService.getLatestList();
        List<String> formTableNameList = latestList.stream().map(FormTableVo::getTableName).collect(Collectors.toList());
        List<DatabaseTableWithColumns> tableList = designService.allTableWithColumns();

        ArrayList<Map<String, String>> mapList = Lists.newArrayList();

        for (DatabaseTableWithColumns databaseTable : tableList) {
            String tableName = databaseTable.getTableName();
            HashMap<String, String> map = new HashMap<>();
            map.put("tableName", tableName);
            if (formTableNameList.contains(tableName)) {
                FormTableVo formTableVo = latestList.stream().filter(entity -> entity.getTableName().equals(tableName)).findFirst().orElse(null);
                if (formTableVo != null) {
                    map.put("tableHeadId", formTableVo.getTableHeadId());
                    map.put("formId", formTableVo.getTableHeadId());
                    map.put("tableCname", formTableVo.getTableCname());
                    map.put("fields", formTableVo.getTableFields());
                    map.put("hasFormId", "true");
                }
            } else {
                map.put("tableHeadId", null);
                map.put("formId", null);
                map.put("tableCname", tableName);
                map.put("fields", databaseTable.getColumns());
                map.put("hasFormId", "false");
            }
            mapList.add(map);
        }

        return mapList;
    }

    @Override
    public List<Map<String, String>> tableList(String searchText) {
        // 表单设计相关的表
        List<FormTableVo> formTableList = designService.getLatestList();
        // 返回数据库中所有表 (里面包含表单设计相关的表)
        List<DatabaseTableWithColumns> allTableList = designService.allTableWithColumns();
        // 获取是表单数据库表名List
        List<String> isFormTableNameList = new ArrayList<>(formTableList.size());

        List<Map<String, String>> data = formTableList.stream().filter(entity -> {
            String tableCname = entity.getTableCname();
            String sourceType = entity.getSourceType();
            if (StringUtils.isNotEmpty(searchText)) {
                return StringUtils.isNotEmpty(tableCname) && tableCname.contains(searchText)
                        && FormConstant.TABLE_SOURCE.AUTO.getCode().equals(sourceType);
            } else {
                return StringUtils.isNotEmpty(tableCname)
                        && FormConstant.TABLE_SOURCE.AUTO.getCode().equals(sourceType);
            }
        }).map(formTableVo -> {
            String tableName = formTableVo.getTableName();
            isFormTableNameList.add(tableName);
            Map<String, String> map = new HashMap<>();
            map.put("tableHeadId", formTableVo.getTableHeadId());
            map.put("formId", formTableVo.getTableHeadId());
            map.put("tableCname", formTableVo.getTableCname());
            map.put("fields", formTableVo.getTableFields());
            map.put("tableName", formTableVo.getTableName());
            map.put("hasFormId", "true");
            return map;
        }).collect(Collectors.toList());

        // 如果包含中文，那么表示只搜索和表单设计相关的表。
        if (StringUtils.isEmpty(searchText) || !CommonUtils.ifContainChinese(searchText)) {
            List<Map<String, String>> allList = allTableList.stream().filter(item -> {
                String tableName = item.getTableName();
                if (StringUtils.isNotEmpty(searchText)) {
                    return tableName.toLowerCase().contains(searchText.toLowerCase()) && !isFormTableNameList.contains(tableName);
                } else {
                    return !isFormTableNameList.contains(tableName);
                }
            }).map(item -> {
                Map<String, String> map = new HashMap<>();
                map.put("tableHeadId", null);
                map.put("formId", null);
                map.put("tableCname", null);
                map.put("tableName", item.getTableName());
                map.put("fields", item.getColumns());
                map.put("hasFormId", "false");
                return map;
            }).collect(Collectors.toList());

            data.addAll(allList);
        }

        return data;
    }

    @Override
    public List<String> getColumnBySql(String sql) {
        ArrayList<String> dataList = new ArrayList<>();

        if (!sql.endsWith("limit 1")) {
            sql += " limit 1";
        }
        Select select = null;
        Statement statement = null;
        try {
            statement = CCJSqlParserUtil.parse(sql);
        } catch (JSQLParserException e) {
            e.printStackTrace();
        }

        // 判断是否是查询语句
        if (statement instanceof Select) {
            select = (Select) statement;
        } else {
            throw new ResultException("只能解析查询语句");
        }

        // 判断是否可以执行, 不能执行就会报错
        pageService.executeSql(sql);

        // 解析查询语句
        SelectBody selectBody = null;
        selectBody = select.getSelectBody();
        PlainSelect plainSelect = (PlainSelect) selectBody;
        List<SelectItem> selectItems = plainSelect.getSelectItems();
        for (SelectItem selectItem : selectItems) {
            if (selectItem instanceof SelectExpressionItem) {
                SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem;
                Expression expression = selectExpressionItem.getExpression();
                if (expression instanceof Column) {
                    Column column = (Column) expression;
                    String columnName = column.getColumnName();
                    if (column.getTable() != null) {
                        Table table = column.getTable();
                        String tableName = table.getName();

                        columnName = tableName + columnName;
                        dataList.add(columnName.toUpperCase());
                    } else {
                        dataList.add(columnName.toUpperCase());
                    }
                }
            }
        }

        return dataList;
    }
}
